import { ElLoading } from 'element-plus'
import type {
  AxiosInstance,
  AxiosProgressEvent,
  AxiosRequestConfig,
  AxiosRequestHeaders,
  AxiosResponse,
  InternalAxiosRequestConfig
} from 'axios'
import axios from 'axios'
import { localCache } from '@/utils/cache'
import message from '@/utils/message'
import type { CustomAxiosRequestConfig, RequestConfig } from './types/requestType'
import { useHomeStore } from '@/stores/home'
import { get } from 'vue-cookies'
console.log(get('token'))
// interface CustomAxiosResponse<T = any, R = any> extends AxiosResponse<T, R> {
//   code: number // 这是一个自定义属性，可以是任何你想要的类型
//   // 注意：不要在这里重新定义 status，因为它已经存在于 AxiosResponse 中
// }

let loading: any
class RequestHttp {
  instance: AxiosInstance
  // 拦截器对象
  // interceptorsObj?: RequestInterceptors
  public constructor(config: AxiosRequestConfig) {
    // 实例化axios
    this.instance = axios.create(config)

    /**
     * @description 请求拦截器
     * 客户端发送请求 -> [请求拦截器] -> 服务器
     * token校验(JWT) : 接受服务器返回的token,存储到vuex/pinia/本地储存当中
     */
    this.instance.interceptors.request.use(
      //版本原因:AxiosRequestConfig 类型不能给config了
      //需要改用 InternalAxiosRequestConfig 类型  但是里面参数会有变化
      //所以暂时不使用 AxiosRequestConfig 类型
      (config: InternalAxiosRequestConfig) => {
        const { showLoading = false } = config.data || {}
        if (showLoading) {
          loading = ElLoading.service({
            lock: true,
            text: '加载中......',
            background: 'rgba(0, 0, 0, 0.7)'
          })
        }
        const token = get('token') || ''
        //设置请求头
        ;(config.headers as AxiosRequestHeaders)['token'] = token
        return config
      },
      (err: any) => {
        if (err.config.showLoading && loading) {
          loading.close()
        }
        console.log('全局请求拦截器失败', err)
        message.error('请求发送失败')
        return Promise.reject('请求发送失败')
      }
    )

    /**
     * @description 响应拦截器
     *  服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
     */
    this.instance.interceptors.response.use(
      (res) => {
        let requestData: any = {}
        // 如果是FormData则不解析
        if (!(res.config.data instanceof FormData)) {
          requestData = res.config.data ? JSON.parse(res.config.data) : {}
        }
        const { showLoading, responseType, errorCallback } = requestData
        // 关闭loading
        if (showLoading && loading) {
          loading.close()
        }
        const responseData = res.data
        if (responseType == 'arraybuffer' || responseType == 'blob') {
          return responseData
        }
        //处理请求
        switch (responseData.code) {
          case 200:
            return responseData
          //处理认证过期
          case 901:
            return handleAuthExpired(responseData)
          default:
            if (errorCallback) {
              errorCallback(responseData)
            }
            return handleApiError(responseData)
        }
      },
      (err) => {
        console.log(err)

        if (err.config.showLoading && loading) {
          loading.close()
        }
        message.error('请求发送失败')
        return Promise.reject({ showError: true, msg: '网络异常' })
      }
    )
  }

  request<T>(config: RequestConfig<T>) {
    return new Promise<T>((resolve, reject) => {
      this.instance
        .request<any, T>(config)
        .then((res) => {
          resolve(res)
        })
        .catch((err: any) => {
          reject(err)
        })
    })
  }

  get<T>(config: RequestConfig<T>) {
    return this.instance.request<T>({ ...config, method: 'GET' })
  }

  post<T>(config: RequestConfig<T>) {
    if (config.data instanceof FormData) {
      config.headers = {
        ...config.headers,
        'Content-Type': 'multipart/form-data'
      }
    }
    return this.instance.request<T>({ ...config, method: 'POST' })
  }

  delete<T = any>(config: RequestConfig<T>) {
    return this.instance.request<T>({ ...config, method: 'DELETE' })
  }

  patch<T = any>(config: RequestConfig<T>) {
    return this.instance.request<T>({ ...config, method: 'PATCH' })
  }

  put<T = any>(config: RequestConfig<T>) {
    if (config.data instanceof FormData) {
      config.headers = {
        ...config.headers,
        'Content-Type': 'multipart/form-data'
      }
    }
    return this.instance.request<T>({ ...config, method: 'PUT' })
  }

  //带有回调函数的请求
  postCallback<T>(config: CustomAxiosRequestConfig): Promise<{
    data: T
    code: number
    info: string
    status: number
  }> {
    return new Promise((resolve, reject) => {
      // 处理FormData类型
      if (config.data instanceof FormData) {
        config.headers = {
          ...config.headers,
          'Content-Type': 'multipart/form-data'
        }
      }

      // 添加进度回调处理
      const axiosConfig: CustomAxiosRequestConfig = {
        ...config,
        method: 'POST',
        onUploadProgress: (progressEvent: AxiosProgressEvent) => {
          if (config.uploadProgressCallback) {
            config.uploadProgressCallback({
              percent: Math.round((progressEvent.loaded * 100) / (progressEvent.total || 1)),
              loaded: progressEvent.loaded,
              total: progressEvent.total || 0,
              event: progressEvent
            })
          }
        }
      }

      this.instance
        .request(axiosConfig)
        .then((res: AxiosResponse<T>) => {
          resolve({
            data: res.data, // 泛型数据
            code: res.code, // HTTP 状态码
            info: res.info, // 自定义信息
            status: res.status // 自定义状态
          })
        })
        .catch((err: any) => {
          // 优先执行自定义错误回调
          if (config.errorCallback) {
            config.errorCallback(err)
          }

          // 默认错误处理
          if (config.showError !== false) {
            const errorMsg = err.msg || err.message || '请求失败'
            message.error(errorMsg)
          }

          reject(err)
        })
    })
  }
}

// 认证过期处理函数
const handleAuthExpired = (responseData: any) => {
  const homeStore = useHomeStore()

  // 标记需要重新登录
  homeStore.setLogin(true)

  // 显示提示信息（如果需要）
  if (responseData.info) {
    message.error(responseData.info || '登录已过期，请重新登录')
  }

  // 清除本地token等凭证
  localCache.removeCache('token')

  // 重定向到登录页
  if (window.location.pathname !== '/login') {
    console.log('重定向到登录页')
    // router.push('/login?redirect=' + encodeURIComponent(window.location.pathname));
  }

  return Promise.reject({
    code: 901,
    type: 'AUTH_EXPIRED',
    showError: false, // 不显示默认错误提示（因为已经处理了）
    originalData: responseData // 保留原始响应数据
  })
}

// API错误处理函数
const handleApiError = (responseData: any) => {
  console.log(responseData)

  // 显示错误信息
  if (responseData.info) {
    message.error(responseData.info)
  }

  // 特殊错误码处理
  if (responseData.code === 902) {
    // 例如：权限不足的特殊处理
    console.log('权限不足的特殊处理')
    // router.push('/no-permission');
  }

  return Promise.reject({
    code: responseData.code,
    type: 'API_ERROR',
    showError: true,
    msg: responseData.info,
    originalData: responseData
  })
}

export default RequestHttp
